<template>
  <div class="session-manage-page">
    <div class="header">
      <h2>会话管理</h2>
      <el-button type="primary" @click="exportDialog.visible = true" style="margin-left: 20px;">导出记录</el-button>
    </div>
    <!-- 批量操作栏 -->
    <div class="batch-bar" v-if="multipleSelection.length">
                <!-- <el-button size="small" @click="batchAssign">批量分配</el-button> -->
      <el-button size="small" type="danger" @click="batchClose">批量结束</el-button>
      <span style="margin-left: 12px; color: #888;">已选 {{ multipleSelection.length }} 项</span>
    </div>
    <!-- 搜索栏 -->
    <div class="search-bar">
      <el-input v-model="search.user" placeholder="用户昵称/手机号" style="width: 220px; margin-right: 12px;" clearable />
      <el-select v-model="search.status" placeholder="会话状态" style="width: 140px; margin-right: 12px;">
        <el-option label="全部" value="" />
        <el-option label="进行中" value="active" />
        <el-option label="已结束" value="closed" />
        <el-option label="待分配" value="pending" />
      </el-select>
      <el-select v-model="search.tag" placeholder="标签筛选" style="width: 140px; margin-right: 12px;" clearable :value="search.tag">
        <el-option v-for="tag in tagOptions" :key="tag.id" :label="tag.name" :value="tag.id" />
      </el-select>
      <el-button type="primary" @click="handleSearch">搜索</el-button>
      <el-button @click="resetSearch">重置</el-button>
    </div>
    <!-- 会话表格 -->
    <el-card>
      <el-table :data="pagedSessions" style="width: 100%" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="48" />
        <el-table-column prop="id" label="会话ID" width="120" />
        <el-table-column prop="userName" label="用户昵称" width="140" />
        <el-table-column prop="userPhone" label="手机号" width="140">
          <template #default="scope">
            {{ maskPhone(scope.row.userPhone) }}
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="100">
          <template #default="scope">
            <el-tag :type="statusTagType(scope.row.status)">{{ statusText(scope.row.status) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="tags" label="标签" min-width="160">
          <template #default="scope">
            <el-tag
              v-for="tid in scope.row.tags"
              :key="tid"
              :type="(tagOptions.find(t => t.id === tid)?.color) || 'info'"
              style="margin-right:4px;"
            >{{ tagOptions.find(t => t.id === tid)?.name || tid }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="startTime" label="开始时间" width="180" />
        <el-table-column prop="lastMessage" label="最后消息" min-width="200" />
        <el-table-column prop="staffName" label="所属客服" width="120" />
        <el-table-column label="解决状态" width="100">
          <template #default="scope">
            <el-tag v-if="scope.row.satisfaction && scope.row.satisfaction.resolved === true" type="success">已解决</el-tag>
            <el-tag v-else-if="scope.row.satisfaction && scope.row.satisfaction.resolved === false" type="danger">未解决</el-tag>
            <el-tag v-else type="info">-</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="220">
          <template #default="scope">
            <el-button size="small" @click="viewDetail(scope.row)">查看</el-button>
            <template v-if="scope.row.status !== 'closed'">
              <el-button size="small" @click="assignStaff(scope.row)">分配</el-button>
              <el-button size="small" @click="transferSession(scope.row)">转接</el-button>
              <el-button size="small" type="danger" @click="closeSession(scope.row)">结束</el-button>
            </template>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        v-model:current-page="page.current"
        v-model:page-size="page.size"
        :total="filteredSessions.length"
        layout="total, sizes, prev, pager, next, jumper"
        :page-sizes="[10, 20, 50, 100]"
        style="margin-top: 16px; text-align: right;"
        @current-change="handlePageChange"
      />
    </el-card>
    <!-- 分配客服弹窗 -->
    <el-dialog v-model="assignDialog.visible" title="分配客服" width="400px">
      <el-input v-model="assignDialog.search" placeholder="搜索客服" style="margin-bottom: 12px;" />
      <el-radio-group v-model="assignDialog.selected">
        <el-radio
          v-for="staff in filteredStaffs"
          :key="staff.id"
          :value="staff.id"
          :disabled="staff.status === 'offline'"
        >
          <el-tag
            :type="staff.status === 'online-free' ? 'success' : staff.status === 'online-busy' ? 'warning' : 'info'"
            size="small"
            style="margin-right: 6px;"
          >
            {{ staff.status === 'online-free' ? '在线-空闲' : staff.status === 'online-busy' ? '在线-忙碌' : '离线' }}
          </el-tag>
          {{ staff.name }}
        </el-radio>
      </el-radio-group>
      <template #footer>
        <el-button @click="assignDialog.visible = false">取消</el-button>
        <el-button type="primary" @click="confirmAssign">确定分配</el-button>
      </template>
    </el-dialog>
    <!-- 转接客服弹窗 -->
    <el-dialog v-model="transferDialog.visible" title="转接客服" width="400px">
      <el-input v-model="transferDialog.search" placeholder="搜索客服" style="margin-bottom: 12px;" />
      <el-radio-group v-model="transferDialog.selected">
        <el-radio
          v-for="staff in filteredStaffsTransfer"
          :key="staff.id"
          :value="staff.id"
          :disabled="staff.status === 'offline'"
        >
          <el-tag
            :type="staff.status === 'online-free' ? 'success' : staff.status === 'online-busy' ? 'warning' : 'info'"
            size="small"
            style="margin-right: 6px;"
          >
            {{ staff.status === 'online-free' ? '在线-空闲' : staff.status === 'online-busy' ? '在线-忙碌' : '离线' }}
          </el-tag>
          {{ staff.name }}
        </el-radio>
      </el-radio-group>
      <template #footer>
        <el-button @click="transferDialog.visible = false">取消</el-button>
        <el-button type="primary" @click="confirmTransfer">确定转接</el-button>
      </template>
    </el-dialog>
    <!-- 会话详情抽屉 -->
    <el-drawer v-model="detailDrawer.visible" title="" size="700px" class="im-drawer">
      <template #default>
        <div class="im-header">
          <div class="im-user-info">
            <div class="im-nick">{{ detailDrawer.session.userName }}</div>
            <div class="im-contact">{{ maskPhone(detailDrawer.session.userPhone) }} <span v-if="detailDrawer.session.userEmail">• {{ detailDrawer.session.userEmail }}</span></div>
            <el-tag :type="statusTagType(detailDrawer.session.status)" size="small" class="im-status">{{ statusText(detailDrawer.session.status) }}</el-tag>
          </div>
          <div class="im-actions">
            <el-button type="warning" size="small" @click="transferSession(detailDrawer.session)" :disabled="detailDrawer.session.status === 'closed'">转接</el-button>
            <el-button type="info" size="small" @click="openAssignCoStaff" :disabled="detailDrawer.session.status === 'closed'">协作</el-button>
            <el-button type="danger" size="small" @click="closeSession(detailDrawer.session)" :disabled="detailDrawer.session.status === 'closed'">结束会话</el-button>
          </div>
        </div>
        <div class="im-main">
          <div class="im-msg-list">
            <div v-for="msg in detailDrawer.session.messages" :key="msg.id" :class="['im-msg', msg.from === 'user' ? 'im-msg-right' : 'im-msg-left', msg.recalled ? 'im-msg-recalled' : '']">
              <div class="im-msg-meta">
                <span class="im-msg-nick">{{ msg.from === 'user' ? detailDrawer.session.userName : msg.senderName }}</span>
                <img class="im-msg-avatar" :src="msg.from === 'user' ? userAvatar : staffAvatar" />
              </div>
              <div class="im-msg-bubble-wrap">
                <div class="im-msg-bubble">
                  <template v-if="msg.recalled"><i style="color:#aaa">该消息已撤回</i></template>
                  <template v-else-if="msg.type === 'text' || !msg.type">{{ msg.content }}</template>
                  <template v-else-if="msg.type === 'image'">
                    <img :src="msg.content" class="im-msg-img" @click="() => previewImg(msg.content)" />
                  </template>
                  <template v-else-if="msg.type === 'emoji'">
                    <span class="im-msg-emoji">{{ msg.content }}</span>
                  </template>
                  <template v-else-if="msg.type === 'voice'">
                    <audio :src="msg.content" controls class="im-msg-voice" />
                  </template>
                  <template v-else-if="msg.type === 'file'">
                    <el-link :href="msg.content" :download="msg.fileName" target="_blank" type="primary">
                      <el-icon style="vertical-align:middle;"><svg width="18" height="18" viewBox="0 0 20 20"><rect x="3" y="3" width="14" height="14" rx="2" fill="#f5f5f5" stroke="#888"/><path d="M7 8h6M7 11h6" stroke="#888" stroke-width="1.2"/></svg></el-icon>
                      {{ msg.fileName }}
                    </el-link>
                  </template>
                  <el-button
                    v-if="canRecall(msg) && detailDrawer.session.status !== 'closed'"
                    size="small"
                    type="text"
                    class="im-msg-recall-btn-float"
                    @click="recallMessage(msg)"
                  >撤回</el-button>
                  <!-- 评价消息 -->
                  <template v-if="msg.type === 'rating'">
                    <div class="im-rating-msg">
                      <span class="im-rating-stars">{{ '⭐'.repeat(msg.rating) }}</span>
                      <span v-if="msg.text">{{ msg.text }}</span>
                      <span v-if="msg.emoji" class="im-rating-emoji">{{ msg.emoji }}</span>
                    </div>
                  </template>
                  <template v-else-if="msg.type === 'invite-rating'">
                    <div class="im-invite-rating">
                      <el-button size="small" type="primary" @click="openRating(detailDrawer.session)">评价本次服务</el-button>
                    </div>
                  </template>
                </div>
              </div>
              <div class="im-msg-time-row">
                <span class="im-msg-time">{{ msg.time }}</span>
                <span v-if="msg.read" class="im-msg-read">已读</span>
                <span v-else class="im-msg-unread">未读</span>
              </div>
            </div>
          </div>
          <div class="im-tab-bar">
            <el-tabs v-model="imTab" class="im-tabs">
              <el-tab-pane label="快捷回复" name="quick">
                <div class="im-tab-content">
                  <el-select v-model="quickReplyGroup" placeholder="选择分组" style="width: 120px; margin-bottom: 8px;">
                    <el-option v-for="g in quickReplyGroups" :key="g" :label="g" :value="g" />
                  </el-select>
                  <el-select v-model="quickReply" placeholder="快捷回复" style="width: 220px;">
                    <el-option v-for="item in filteredQuickReplies" :key="item.id" :label="item.content" :value="item.content" />
                  </el-select>
                </div>
              </el-tab-pane>
              <el-tab-pane label="知识库" name="kb">
                <div class="im-tab-content">
                  <el-input placeholder="搜索知识库内容..." style="width: 220px; margin-bottom: 8px;" />
                  <div class="im-kb-empty">暂无知识库内容</div>
                </div>
              </el-tab-pane>
            </el-tabs>
          </div>
        </div>
        <div class="im-input-bar">
          <el-input v-model="detailDrawer.input" placeholder="输入消息..." class="im-input" @keyup.enter="sendMessage" :maxlength="500" show-word-limit />
          <el-button class="im-btn" @click="triggerFileUpload"><svg width="20" height="20" viewBox="0 0 20 20"><path d="M6 10v4a4 4 0 0 0 8 0V6a2 2 0 0 0-4 0v8a1 1 0 0 0 2 0V7" stroke="#888" stroke-width="1.5" fill="none"/><circle cx="10" cy="10" r="9" stroke="#888" stroke-width="1.2" fill="none"/></svg> 附件</el-button>
          <input type="file" ref="fileInput" style="display:none" @change="onFileChange" />
          <el-button class="im-btn" @click="showEmojiPanel = !showEmojiPanel"><svg width="20" height="20" viewBox="0 0 20 20"><text x="2" y="16" font-size="16">😃</text></svg> 表情</el-button>
          <el-button class="im-btn im-btn-send" type="primary" @click="sendMessage">发送</el-button>
          <div v-if="showEmojiPanel" class="emoji-panel im-emoji-panel">
            <span v-for="emoji in emojiList" :key="emoji" class="emoji-item" @click="insertEmoji(emoji)">{{ emoji }}</span>
          </div>
        </div>
        <el-dialog v-model="showImgPreview" width="auto" :show-close="true" center>
          <img :src="previewImgUrl" style="max-width:480px;max-height:480px;display:block;margin:auto;" />
        </el-dialog>
      </template>
    </el-drawer>
    <!-- 分配主客服弹窗 -->
    <el-dialog v-model="mainStaffDialog.visible" title="分配主客服" width="400px" :before-close="onDialogBeforeClose">
      <el-radio-group v-model="mainStaffDialog.selected" :disabled="detailDrawer.session && detailDrawer.session.status === 'closed'">
        <el-radio v-for="staff in mockStaffs" :key="staff.id" :value="staff.id">{{ staff.name }}</el-radio>
      </el-radio-group>
      <template #footer>
        <el-button @click="mainStaffDialog.visible = false">取消</el-button>
        <el-button type="primary" @click="confirmAssignMainStaff" :disabled="detailDrawer.session && detailDrawer.session.status === 'closed'">确定分配</el-button>
      </template>
    </el-dialog>
    <!-- 分配协同客服弹窗 -->
    <el-dialog v-model="coStaffDialog.visible" title="添加协同客服" width="400px" :before-close="onDialogBeforeClose">
      <el-select v-model="coStaffDialog.selected" multiple filterable placeholder="请选择协同客服" style="width:100%" :disabled="detailDrawer.session && detailDrawer.session.status === 'closed'">
        <el-option v-for="staff in mockStaffs" :key="staff.id" :label="staff.name" :value="staff.id">
          <el-tag
            :type="staff.status === 'online-free' ? 'success' : staff.status === 'online-busy' ? 'warning' : 'info'"
            size="small"
            style="margin-right: 6px;"
          >
            {{ staff.status === 'online-free' ? '在线-空闲' : staff.status === 'online-busy' ? '在线-忙碌' : '离线' }}
          </el-tag>
          {{ staff.name }}
        </el-option>
      </el-select>
      <template #footer>
        <el-button @click="coStaffDialog.visible = false">取消</el-button>
        <el-button type="primary" @click="confirmAssignCoStaff" :disabled="detailDrawer.session && detailDrawer.session.status === 'closed'">确定添加</el-button>
      </template>
    </el-dialog>
    <!-- 导出记录弹窗 -->
    <el-dialog v-model="exportDialog.visible" title="导出聊天记录" width="500px">
      <el-form :model="exportForm" label-width="100px">
        <el-form-item label="选择会话">
          <el-select
            v-model="exportForm.sessionIds"
            placeholder="请选择要导出的会话"
            filterableß
            multiple
            collapse-tags
            collapse-tags-tooltip
            style="width: 100%;"
          >
            <el-option
              v-for="session in closedSessions"
              :key="session.id"
              :label="`${session.userName} - ${session.startTime}`"
              :value="session.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="导出格式">
          <el-radio-group v-model="exportForm.format">
            <el-radio value="txt">TXT</el-radio>
            <el-radio value="json">JSON</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="exportDialog.visible = false">取消</el-button>
        <el-button type="primary" @click="handleExport" :disabled="!exportForm.sessionIds.length">确定导出</el-button>
      </template>
    </el-dialog>
    <!-- 评价弹窗 -->
    <el-dialog v-model="ratingDialog.visible" title="服务评价" width="400px">
      <div style="margin-bottom: 12px;">星级：
        <el-rate v-model="ratingDialog.rating" :max="5" allow-half />
      </div>
      <el-input v-model="ratingDialog.text" placeholder="评价内容（可选）" maxlength="100" show-word-limit style="margin-bottom: 12px;" />
      <div style="margin-bottom: 12px;">表情：
        <span v-for="emoji in emojiList" :key="emoji" class="emoji-item" @click="ratingDialog.emoji = emoji" :style="{fontSize:'22px',marginRight:'8px',cursor:'pointer',border:ratingDialog.emoji===emoji?'1.5px solid #4361ee':'none',borderRadius:'4px'}">{{ emoji }}</span>
      </div>
      <div style="margin-bottom: 12px;">问题是否已解决：
        <el-radio-group v-model="ratingDialog.resolved">
          <el-radio :label="true">已解决</el-radio>
          <el-radio :label="false">未解决</el-radio>
        </el-radio-group>
      </div>
      <el-button type="primary" @click="submitRating">提交评价</el-button>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'

// mock数据
const allSessions = ref([
  { id: 'S1001', userName: '张三', userPhone: '13800000001', status: 'active', startTime: '2024-06-01 10:00', lastMessage: '请问我的订单什么时候发货？', staffName: '客服A', staffId: 'A', coStaffIds: ['B'], tags: [1, 3] },
  { id: 'S1002', userName: '李四', userPhone: '13800000002', status: 'pending', startTime: '2024-06-01 10:10', lastMessage: '您好，有人吗？', staffName: '', staffId: '', coStaffIds: [], tags: [] },
  { id: 'S1003', userName: '王五', userPhone: '13800000003', status: 'closed', startTime: '2024-05-31 16:20', lastMessage: '谢谢您的帮助', staffName: '客服B', staffId: 'B', coStaffIds: [], tags: [4] },
  { id: 'S1004', userName: '赵六', userPhone: '13800000004', status: 'active', startTime: '2024-06-01 11:00', lastMessage: '我想退货', staffName: '客服A', staffId: 'A', coStaffIds: ['C', 'D'], tags: [2, 3] },
  { id: 'S1005', userName: '小明', userPhone: '13800000005', status: 'active', startTime: '2024-06-01 11:20', lastMessage: '收到货了', staffName: '客服C', staffId: 'C', coStaffIds: [], tags: [] },
  { id: 'S1006', userName: '小红', userPhone: '13800000006', status: 'pending', startTime: '2024-06-01 11:30', lastMessage: '请尽快回复', staffName: '', staffId: '', coStaffIds: [], tags: [] },
  { id: 'S1007', userName: '周七', userPhone: '13800000007', status: 'closed', startTime: '2024-06-02 09:00', lastMessage: '问题已解决，感谢。', staffName: '客服A', staffId: 'A', coStaffIds: [], tags: [] },
  { id: 'S1008', userName: '吴八', userPhone: '13800000008', status: 'closed', startTime: '2024-06-02 14:00', lastMessage: '非常满意！', staffName: '客服C', staffId: 'C', coStaffIds: [], tags: [4] },
  { id: 'S1009', userName: '郑九', userPhone: '13800000009', status: 'closed', startTime: '2024-06-03 11:00', lastMessage: '好的，我了解了。', staffName: '客服B', staffId: 'B', coStaffIds: [], tags: [3] },
])
// 标签mock数据（与TagManage保持同步）
const tagOptions = ref([
  { id: 1, name: '投诉', color: 'danger' },
  { id: 2, name: '催单', color: 'warning' },
  { id: 3, name: '售后', color: 'info' },
  { id: 4, name: '高价值客户', color: 'success' }
])

const mockStaffs = [
  { id: 'A', name: '客服A', status: 'online-free' },
  { id: 'B', name: '客服B', status: 'online-busy' },
  { id: 'C', name: '客服C', status: 'offline' },
  { id: 'D', name: '客服D', status: 'online-free' }
]

// mock快捷回复分组和内容
const quickReplyGroups = ref(['常用', '售后', '物流', '投诉'])
const quickReplyList = ref([
  { id: 1, content: '您好，请问有什么可以帮您？', group: '常用' },
  { id: 2, content: '您的问题已收到，我们会尽快处理。', group: '常用' },
  { id: 3, content: '感谢您的反馈，祝您生活愉快！', group: '常用' },
  { id: 4, content: '您的订单已发货，请注意查收。', group: '物流' },
  { id: 5, content: '如有疑问，欢迎随时联系。', group: '售后' }
])
const quickReplyGroup = ref('常用')
const quickReply = ref('')
const filteredQuickReplies = computed(() => quickReplyList.value.filter(r => r.group === quickReplyGroup.value))

const search = ref<{ user: string; status: string; tag: number | null }>({ user: '', status: '', tag: null })
const page = ref({ current: 1, size: 5 })
const multipleSelection = ref<any[]>([])

// --- 导出记录 ---
const exportDialog = ref({ visible: false });
const exportForm = ref<{ sessionIds: string[]; format: 'txt' | 'json' }>({
  sessionIds: [],
  format: 'txt',
});
const closedSessions = computed(() => allSessions.value.filter(s => s.status === 'closed'));

const handleExport = () => {
    if (exportForm.value.sessionIds.length === 0) {
        ElMessage.error('请至少选择一个会话');
        return;
    }

    const selectedSessions = allSessions.value.filter(s => exportForm.value.sessionIds.includes(s.id));

    if (selectedSessions.length === 0) {
        ElMessage.error('未找到任何有效会话');
        return;
    }

    let fileContent = '';
    let fileType = '';
    const timestamp = new Date().toISOString().slice(0, 10);
    let fileName = `批量会话记录_${timestamp}`;

    if (exportForm.value.format === 'txt') {
        selectedSessions.forEach(session => {
            const messages = [
                { from: 'user', content: '您好', time: '2024-06-01 10:00' },
                { from: 'staff', content: '您好，请问有什么可以帮您？', time: '2024-06-01 10:01' },
                { from: 'user', content: session.lastMessage, time: session.startTime }
            ];
            fileContent += `\n\n======== 会话ID: ${session.id} | 用户: ${session.userName} ========\n\n`;
            fileContent += messages.map(m => `[${m.time}] ${m.from === 'user' ? session.userName : '客服'}: ${m.content}`).join('\n');
        });
        fileType = 'text/plain';
        fileName += '.txt';
    } else {
        const exportData = selectedSessions.map(session => {
            const messages = [
                 { from: 'user', content: '您好', time: '2024-06-01 10:00' },
                { from: 'staff', content: '您好，请问有什么可以帮您？', time: '2024-06-01 10:01' },
                { from: 'user', content: session.lastMessage, time: session.startTime }
            ];
            return { session, messages };
        });
        fileContent = JSON.stringify(exportData, null, 2);
        fileType = 'application/json';
        fileName += '.json';
    }

    const blob = new Blob([fileContent], { type: fileType });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    a.click();
    URL.revokeObjectURL(url);

    exportDialog.value.visible = false;
    ElMessage.success('批量导出成功');
};


const filteredSessions = computed(() => {
  let list = allSessions.value
  if (search.value.user) {
    list = list.filter(s => s.userName.includes(search.value.user) || s.userPhone.includes(search.value.user))
  }
  if (search.value.status) {
    list = list.filter(s => s.status === search.value.status)
  }
  if (search.value.tag !== null) {
    list = list.filter(s => Array.isArray(s.tags) && s.tags.includes(search.value.tag as number))
  }
  return list
})

const pagedSessions = computed(() => {
  const start = (page.value.current - 1) * page.value.size
  return filteredSessions.value.slice(start, start + page.value.size)
})

function handleSearch() {
  page.value.current = 1
}
function resetSearch() {
  search.value.user = ''
  search.value.status = ''
  search.value.tag = null
  page.value.current = 1
}
function handlePageChange(val: number) {
  page.value.current = val
}
function statusText(status: string) {
  if (status === 'active') return '进行中'
  if (status === 'closed') return '已结束'
  if (status === 'pending') return '待分配'
  return status
}
function statusTagType(status: string) {
  if (status === 'active') return 'success'
  if (status === 'closed') return 'info'
  if (status === 'pending') return 'warning'
  return 'default'
}
function handleSelectionChange(val: any[]) {
  multipleSelection.value = val
}
// 分配客服弹窗
const assignDialog = ref<{ visible: boolean; session: any; search: string; selected: string; batch: boolean }>({ visible: false, session: null, search: '', selected: '', batch: false })
const filteredStaffs = computed(() => {
  if (!assignDialog.value.search) return mockStaffs
  return mockStaffs.filter(s => s.name.includes(assignDialog.value.search))
})
function assignStaff(row: any) {
  assignDialog.value.visible = true
  assignDialog.value.session = row
  assignDialog.value.selected = row.staffName ? (mockStaffs.find(s => s.name === row.staffName)?.id || '') : ''
  assignDialog.value.batch = false
}
// 批量分配客服功能 - 已隐藏
// function batchAssign() {
//   assignDialog.value.visible = true
//   assignDialog.value.session = null
//   assignDialog.value.selected = ''
//   assignDialog.value.batch = true
// }
function confirmAssign() {
  if (!assignDialog.value.selected) {
    ElMessage.warning('请选择客服')
    return
  }
  const staff = mockStaffs.find(s => s.id === assignDialog.value.selected)
  const staffName = staff?.name || ''
  // 批量分配客服功能 - 已隐藏
  // if (assignDialog.value.batch) {
  //   multipleSelection.value.forEach(row => { row.staffName = staffName })
  //   ElMessage.success('批量分配成功（mock）')
  // } else 
  if (assignDialog.value.session) {
    assignDialog.value.session.staffName = staffName
    ElMessage.success('分配成功（mock）')
  }
  assignDialog.value.visible = false
}
// 批量结束
function batchClose() {
  multipleSelection.value.forEach(row => { row.status = 'closed' })
  ElMessage.success('批量结束成功（mock）')
}
// 转接客服弹窗
const transferDialog = ref({ visible: false, session: null as any, search: '', selected: '' })
const filteredStaffsTransfer = computed(() => {
  if (!transferDialog.value.search) return mockStaffs
  return mockStaffs.filter(s => s.name.includes(transferDialog.value.search))
})
function transferSession(row: any) {
  transferDialog.value.visible = true
  transferDialog.value.session = row
  transferDialog.value.selected = ''
}
function confirmTransfer() {
  if (!transferDialog.value.selected) {
    ElMessage.warning('请选择要转接的客服')
    return
  }
  const staff = mockStaffs.find(s => s.id === transferDialog.value.selected)
  const staffName = staff?.name || ''
  if (transferDialog.value.session) {
    transferDialog.value.session.staffName = staffName
    ElMessage.success('转接成功（mock）')
  }
  transferDialog.value.visible = false
}
// 会话详情抽屉
const detailDrawer = ref({ visible: false, session: null as any, messages: [] as any[], input: '' as string })
function viewDetail(row: any) {
  detailDrawer.value.visible = true
  detailDrawer.value.session = row
  if (!Array.isArray(detailDrawer.value.session.tags)) {
    detailDrawer.value.session.tags = []
  }
  // 只在首次无messages时mock初始化，否则保留原有消息
  if (!Array.isArray(detailDrawer.value.session.messages) || !detailDrawer.value.session.messages.length) {
    detailDrawer.value.session.messages = [
      { id: 1, from: 'user', content: '您好', time: '2024-06-01 10:00', read: false, recalled: false },
      { id: 2, from: 'staff', content: '您好，请问有什么可以帮您？', time: '2024-06-01 10:01', read: false, recalled: false },
      { id: 3, from: 'user', content: typeof row.lastMessage === 'string' ? row.lastMessage : '', time: typeof row.startTime === 'string' ? row.startTime : '', read: false, recalled: false }
    ]
  }
  // 打开详情时全部设为已读
  setTimeout(() => {
    detailDrawer.value.session.messages.forEach((m: any) => m.read = true)
  }, 500)
  detailDrawer.value.input = ''
  quickReply.value = ''
}
// 消息撤回相关
function canRecall(msg: any) {
  // 仅允许撤回自己（客服）2分钟内且未撤回的消息
  if (msg.from !== 'staff' || msg.recalled) return false
  const now = Date.now()
  // msg.id为时间戳
  const diff = now - (typeof msg.id === 'number' ? msg.id : 0)
  if (diff > 2 * 60 * 1000) return false
  // 主客服可撤回所有客服消息，协同客服只能撤回自己消息
  if (detailDrawer.value.session.staffId === currentStaffId.value) return true
  if (msg.senderId === currentStaffId.value) return true
  return false
}
function recallMessage(msg: any) {
  msg.recalled = true
  msg.content = ''
  ElMessage.success('消息已撤回')
}
// 详情页主/协同客服展示与管理
const mainStaffDialog = ref({ visible: false, selected: '' })
function openAssignMainStaff() {
  if (detailDrawer.value.session && detailDrawer.value.session.status === 'closed') return
  mainStaffDialog.value.selected = detailDrawer.value.session.staffId || ''
  mainStaffDialog.value.visible = true
}
function confirmAssignMainStaff() {
  if (detailDrawer.value.session && detailDrawer.value.session.status === 'closed') return
  if (!mainStaffDialog.value.selected) return
  detailDrawer.value.session.staffId = mainStaffDialog.value.selected
  detailDrawer.value.session.staffName = mockStaffs.find(s => s.id === mainStaffDialog.value.selected)?.name || ''
  mainStaffDialog.value.visible = false
}
const coStaffDialog = ref({ visible: false, selected: [] as string[] })
function openAssignCoStaff() {
  if (detailDrawer.value.session && detailDrawer.value.session.status === 'closed') return
  coStaffDialog.value.selected = [...(detailDrawer.value.session.coStaffIds || [])]
  coStaffDialog.value.visible = true
}
function confirmAssignCoStaff() {
  if (detailDrawer.value.session && detailDrawer.value.session.status === 'closed') return
  detailDrawer.value.session.coStaffIds = [...coStaffDialog.value.selected]
  coStaffDialog.value.visible = false
}
function removeCoStaff(cid: string) {
  if (detailDrawer.value.session && detailDrawer.value.session.status === 'closed') return
  // 主客服可移除，协同客服只能移除自己
  if (detailDrawer.value.session.staffId === currentStaffId.value || cid === currentStaffId.value) {
    detailDrawer.value.session.coStaffIds = (detailDrawer.value.session.coStaffIds || []).filter((id: string) => id !== cid)
    if (cid === currentStaffId.value) {
      ElMessage.success('已退出协同')
    }
  } else {
    ElMessage.warning('无权限移除该协同客服')
  }
}
// mock当前登录客服id
const currentStaffId = ref('A')
// 详情页输入区增加身份选择
const currentSenderId = ref('')
watch(() => detailDrawer.value.session, (session) => {
  // 默认选中当前登录客服身份（主/协同）
  if (!session) return
  if (session.staffId === currentStaffId.value) {
    currentSenderId.value = session.staffId
  } else if (session.coStaffIds && session.coStaffIds.includes(currentStaffId.value)) {
    currentSenderId.value = currentStaffId.value
  } else {
    currentSenderId.value = session.staffId || ''
  }
}, { immediate: true })
// 1. 消息结构支持type字段
// type: 'text' | 'image' | 'emoji' | 'voice'
// 2. mock头像
const userAvatar = 'https://cdn.jsdelivr.net/gh/ChongZeWei/cdn-assets@main/avatar-user.png'
const staffAvatar = 'https://cdn.jsdelivr.net/gh/ChongZeWei/cdn-assets@main/avatar-staff.png'
// 3. mock表情
const emojiList = ['😀','😂','😍','😢','😡','👍','👏','🎉','🥳','🤔','😎','😭','😅','😆','😏','😱','😴','😇','😜','🤗','😤']
const showEmojiPanel = ref(false)
function insertEmoji(emoji: string) {
  detailDrawer.value.input += emoji
  showEmojiPanel.value = false
}
// 4. mock图片上传
const imageInput = ref<HTMLInputElement | null>(null)
function onImageChange(e: Event) {
  const files = (e.target as HTMLInputElement).files
  if (files && files[0]) {
    const url = URL.createObjectURL(files[0])
    detailDrawer.value.messages.push({
      id: Date.now(),
      from: 'staff',
      staffId: currentSenderId.value,
      senderId: currentSenderId.value,
      senderName: mockStaffs.find(s => s.id === currentSenderId.value)?.name || '',
      role: detailDrawer.value.session.staffId === currentSenderId.value ? 'main' : 'co',
      type: 'image',
      content: url,
      time: new Date().toLocaleTimeString(),
      read: true,
      recalled: false
    })
  }
}
function triggerImageUpload() {
  imageInput.value?.click()
}
// 5. mock语音上传
const voiceInput = ref<HTMLInputElement | null>(null)
function onVoiceChange(e: Event) {
  const files = (e.target as HTMLInputElement).files
  if (files && files[0]) {
    const url = URL.createObjectURL(files[0])
    detailDrawer.value.messages.push({
      id: Date.now(),
      from: 'staff',
      staffId: currentSenderId.value,
      senderId: currentSenderId.value,
      senderName: mockStaffs.find(s => s.id === currentSenderId.value)?.name || '',
      role: detailDrawer.value.session.staffId === currentSenderId.value ? 'main' : 'co',
      type: 'voice',
      content: url,
      time: new Date().toLocaleTimeString(),
      read: true,
      recalled: false
    })
  }
}
function triggerVoiceUpload() {
  voiceInput.value?.click()
}
// mock附件上传
const fileInput = ref<HTMLInputElement | null>(null)
function onFileChange(e: Event) {
  const files = (e.target as HTMLInputElement).files
  if (files && files[0]) {
    const url = URL.createObjectURL(files[0])
    detailDrawer.value.messages.push({
      id: Date.now(),
      from: 'staff',
      staffId: currentSenderId.value,
      senderId: currentSenderId.value,
      senderName: mockStaffs.find(s => s.id === currentSenderId.value)?.name || '',
      role: detailDrawer.value.session.staffId === currentSenderId.value ? 'main' : 'co',
      type: 'file',
      content: url,
      fileName: files[0].name,
      time: new Date().toLocaleTimeString(),
      read: true,
      recalled: false
    })
  }
}
function triggerFileUpload() {
  fileInput.value?.click()
}
// 发送消息时带上type字段
function sendMessage() {
  if (detailDrawer.value.session && detailDrawer.value.session.status === 'closed') return
  const inputVal = typeof detailDrawer.value.input === 'string' ? detailDrawer.value.input : ''
  if (!inputVal.trim()) return
  if (!currentSenderId.value) {
    ElMessage.warning('请选择发送身份')
    return
  }
  // 发送人信息
  const staff = mockStaffs.find(s => s.id === currentSenderId.value)
  let role: 'main' | 'co' = 'co'
  if (detailDrawer.value.session.staffId === currentSenderId.value) role = 'main'
  // 判断是否为纯emoji
  const isEmoji = emojiList.includes(inputVal)
  detailDrawer.value.messages.push({
    id: Date.now(),
    from: 'staff',
    staffId: currentSenderId.value,
    senderId: currentSenderId.value,
    senderName: staff?.name || '',
    role,
    type: isEmoji ? 'emoji' : 'text',
    content: inputVal,
    time: new Date().toLocaleTimeString(),
    read: true,
    recalled: false
  })
  detailDrawer.value.input = ''
  quickReply.value = ''
}
// 快捷回复插入
watch(quickReply, (val) => {
  if (val) detailDrawer.value.input = val
})
// 导出聊天记录
function exportChat() {
  if (!detailDrawer.value.session) return
  const lines = detailDrawer.value.messages.map(m => `[${m.time}] ${m.from === 'user' ? '用户' : '客服'}: ${m.content}`)
  const content = lines.join('\n')
  const blob = new Blob([content], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `会话_${detailDrawer.value.session.id}.txt`
  a.click()
  URL.revokeObjectURL(url)
}
// 评价相关
const ratingDialog = ref({ visible: false, session: null as any, rating: 5, text: '', emoji: '', resolved: true })
function openRating(session: any) {
  ratingDialog.value.visible = true
  ratingDialog.value.session = session
  ratingDialog.value.rating = 5
  ratingDialog.value.text = ''
  ratingDialog.value.emoji = ''
  ratingDialog.value.resolved = true
}
function submitRating() {
  if (!ratingDialog.value.session) return
  // 只保存到session，不插入消息区
  ratingDialog.value.session.satisfaction = {
    rating: ratingDialog.value.rating,
    text: ratingDialog.value.text,
    emoji: ratingDialog.value.emoji,
    resolved: ratingDialog.value.resolved,
    time: new Date().toLocaleString()
  }
  ratingDialog.value.session.hasRated = true
  ratingDialog.value.visible = false
  ElMessage.success('评价已提交')
}
function autoDefaultRating(session: any) {
  if (session.hasRated) return
  // 只保存到session，不插入消息区
  session.satisfaction = {
    rating: 5,
    text: '默认五星好评',
    emoji: '😃',
    resolved: true,
    time: new Date().toLocaleString()
  }
  session.hasRated = true
}
function closeSession(row: any) {
  row.status = 'closed'
  // 自动插入评价邀请消息
  if (!Array.isArray(row.messages)) row.messages = []
  row.messages.push({
    id: Date.now(),
    from: 'system',
    type: 'invite-rating',
    content: '请对本次服务进行评价',
    time: new Date().toLocaleString(),
    read: true,
    recalled: false
  })
  ElMessage.success('会话已结束')
  // 30秒后自动五星好评（mock，实际可设更长）
  setTimeout(() => autoDefaultRating(row), 30000)
}
// 脚本部分增加弹窗关闭钩子，禁止已结束会话弹窗操作
function onDialogBeforeClose(done: () => void) {
  if (detailDrawer.value.session && detailDrawer.value.session.status === 'closed') {
    done()
    return
  }
  done()
}
// 图片预览
const previewImgUrl = ref('')
const showImgPreview = ref(false)
function previewImg(url: string) {
  previewImgUrl.value = url
  showImgPreview.value = true
}
// 手机号脱敏函数
function maskPhone(phone: string) {
  if (!phone) return ''
  return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
// 脚本部分增加imTab
const imTab = ref('quick')
</script>

<style scoped>
.session-manage-page {
  padding: 24px;
  background: #f7f8fa;
  min-height: 100vh;
}
.header {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
}
.header h2 {
  margin: 0;
  color: #333;
}
.search-bar {
  margin-bottom: 18px;
  display: flex;
  align-items: center;
}
.batch-bar {
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.detail-user, .detail-staff, .detail-status {
  margin-bottom: 8px;
  font-size: 15px;
}
.detail-actions {
  margin-bottom: 10px;
  display: flex;
  gap: 8px;
}
.detail-messages {
  background: #f8f9fa;
  border-radius: 6px;
  padding: 12px;
  min-height: 120px;
  max-height: 360px;
  overflow-y: auto;
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.msg-bubble {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  max-width: 80%;
}
.msg-left {
  flex-direction: row;
  align-self: flex-start;
}
.msg-right {
  flex-direction: row-reverse;
  align-self: flex-end;
}
.msg-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  background: #eee;
}
.msg-content-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.msg-meta {
  font-size: 12px;
  color: #888;
  margin-bottom: 2px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.msg-nick {
  font-weight: bold;
  color: #333;
}
.msg-content {
  background: #fff;
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 15px;
  word-break: break-all;
  box-shadow: 0 1px 2px rgba(0,0,0,0.03);
  min-width: 36px;
  min-height: 24px;
}
.msg-right .msg-content {
  background: #d2f9d1;
}
.msg-img {
  max-width: 120px;
  max-height: 120px;
  border-radius: 6px;
  cursor: pointer;
  display: block;
}
.msg-emoji {
  font-size: 28px;
  line-height: 1.2;
}
.msg-voice {
  width: 120px;
  vertical-align: middle;
}
.emoji-panel {
  position: absolute;
  bottom: 56px;
  left: 180px;
  background: #fff;
  border: 1px solid #eee;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  padding: 8px 12px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  z-index: 10;
}
.emoji-item {
  font-size: 22px;
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  transition: background 0.15s;
}
.emoji-item:hover {
  background: #f0f0f0;
}
.msg-recalled .msg-content {
  color: #aaa;
  font-style: italic;
}
.im-drawer >>> .el-drawer__body {
  padding: 0;
  background: #f7f8fa;
}
.im-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 28px 10px 28px;
  border-bottom: 1.5px solid #ececec;
  background: #fff;
}
.im-user-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.im-nick {
  font-size: 18px;
  font-weight: bold;
  color: #222;
}
.im-contact {
  font-size: 13px;
  color: #888;
}
.im-status {
  margin-top: 4px;
  align-self: flex-start;
}
.im-actions {
  display: flex;
  gap: 12px;
}
.im-main {
  display: flex;
  flex-direction: column;
  height: 420px;
  background: #f7f8fa;
}
.im-msg-list {
  flex: 1;
  overflow-y: auto;
  padding: 18px 32px 8px 32px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.im-msg {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  max-width: 70%;
  margin-left: auto;
  position: relative;
}
.im-msg-left {
  align-items: flex-start;
  margin-left: 0;
  margin-right: auto;
}
.im-msg-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 2px;
}
.im-msg-nick {
  font-size: 13px;
  color: #666;
  font-weight: 500;
}
.im-msg-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  margin-left: 6px;
  background: #eee;
}
.im-msg-left .im-msg-avatar {
  margin-left: 0;
  margin-right: 6px;
}
.im-msg-bubble-wrap {
  position: relative;
  display: inline-block;
}
.im-msg-bubble {
  background: #fff;
  border-radius: 18px 18px 4px 18px;
  padding: 10px 16px;
  font-size: 16px;
  word-break: break-all;
  box-shadow: 0 1px 2px rgba(0,0,0,0.03);
  min-width: 36px;
  min-height: 24px;
  max-width: 340px;
  margin-bottom: 4px;
}
.im-msg-right .im-msg-bubble {
  background: #d2f9d1;
  border-radius: 18px 18px 18px 4px;
}
.im-msg-emoji {
  font-size: 32px;
  line-height: 1.2;
}
.im-msg-img {
  max-width: 120px;
  max-height: 120px;
  border-radius: 8px;
  cursor: pointer;
  display: block;
}
.im-msg-voice {
  width: 120px;
  vertical-align: middle;
}
.im-msg-time {
  font-size: 12px;
  color: #aaa;
  margin-top: 2px;
  margin-bottom: 0;
  align-self: flex-end;
}
.im-msg-left .im-msg-time {
  align-self: flex-start;
}
.im-msg-unread {
  margin-left: 8px;
  font-size: 12px;
}
.im-msg-recall-btn {
  position: absolute;
  left: -54px;
  top: 8px;
}
.im-msg-recall-btn-float {
  position: absolute;
  top: -18px;
  right: 0;
  z-index: 2;
  background: #fff;
  border-radius: 8px;
  font-size: 12px;
  color: #f56c6c;
  padding: 0 8px;
  height: 22px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
  border: 1px solid #f5c6cb;
  line-height: 20px;
}
.im-msg-bubble-wrap:hover .im-msg-recall-btn-float {
  display: block;
}
.im-tab-bar {
  background: #fff;
  border-top: 1.5px solid #ececec;
  padding: 0 28px;
}
.im-tabs {
  margin-top: 0;
}
.im-tab-content {
  padding: 12px 0 8px 0;
  display: flex;
  gap: 12px;
  align-items: center;
}
.im-kb-empty {
  color: #bbb;
  font-size: 15px;
  margin-top: 18px;
}
.im-input-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #fff;
  border-top: 1.5px solid #ececec;
  padding: 14px 28px 14px 28px;
  position: sticky;
  bottom: 0;
  z-index: 2;
}
.im-input {
  flex: 1;
  border-radius: 18px;
  font-size: 16px;
  padding: 8px 16px;
  background: #f7f8fa;
  border: 1.5px solid #ececec;
}
.im-btn {
  border-radius: 12px;
  font-size: 15px;
  padding: 0 14px;
  display: flex;
  align-items: center;
  gap: 4px;
  background: #f5f5f5;
  border: none;
  color: #444;
}
.im-btn-send {
  background: #3a7afe;
  color: #fff;
  font-weight: bold;
  border: none;
  box-shadow: 0 2px 8px rgba(58,122,254,0.08);
}
.im-emoji-panel {
  left: auto;
  right: 120px;
  bottom: 56px;
}
.im-msg-time-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  color: #aaa;
  margin-top: 2px;
  margin-bottom: 0;
  align-self: flex-end;
}
.im-msg-left .im-msg-time-row {
  align-self: flex-start;
}
.im-msg-read {
  color: #67c23a;
  font-weight: 500;
}
.im-msg-unread {
  color: #f56c6c;
  font-weight: 500;
}
.im-rating-msg { color: #222; font-size: 16px; margin: 6px 0; }
.im-rating-stars { color: #f7b500; font-size: 18px; margin-right: 8px; }
.im-rating-emoji { font-size: 20px; margin-left: 6px; }
.im-invite-rating { margin: 8px 0; }
.emoji-item:hover { background: #f0f4ff; }
</style> 